Micron Document
ZgRNS Git Node

Node / mirrors / micropython-reticulum / files / firmware / example_nomadnet_node.py

Displaying Raw • Download

firmware/example_nomadnet_node.py rns-152-frame-hardening (97447676) Text, 9.75 KB

T8b949e"""
µReticulum Example: NomadNet Page-Serving Node
================================================
Serves simple micron-format pages to NomadNet clients over Reticulum Links.
Pages are loaded from the pages/ directory as .mu (micron format) files.

Supported template variables in .mu files:
{node_name} — node display name from config
{mem_free} — free heap memory in bytes
{uptime} — system uptime in seconds (epoch)
{sensor} — output from all active peripherals

Usage (MicroPython on ESP32-S3 / RP2040):
1. Edit config.py — set WiFi credentials and interfaces
2. Copy the urns/ folder, config.py, pages/, and this file to the device
3. Uncomment peripherals you have connected below
4. Run with: import example_nomadnet_node
"""

Tff7b72from T7ee787config Tff7b72import Te6edf3WIFI_SSIDTb4b4b4, Te6edf3WIFI_PASSTb4b4b4, Te6edf3NODE_NAMETb4b4b4, Te6edf3DEBUGTb4b4b4, Te6edf3CONFIG

Tff7b72import T7ee787gc
Tff7b72import T7ee787time
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)
Te6edf3_boot_time Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)

T8b949e# ---- Peripherals ----
T8b949e# Uncomment the ones you have connected. Shared I2C bus for I2C devices.
Tff7b72from T7ee787machine Tff7b72import Te6edf3PinTb4b4b4, Te6edf3SoftI2C
Te6edf3i2c Tff7b72= Te6edf3SoftI2CTb4b4b4(Te6edf3sclTff7b72=Te6edf3PinTb4b4b4(T79c0ff6Tb4b4b4)Tb4b4b4, Te6edf3sdaTff7b72=Te6edf3PinTb4b4b4(T79c0ff5Tb4b4b4)Tb4b4b4, Te6edf3freqTff7b72=T79c0ff100000Tb4b4b4)

Tff7b72import T7ee787peripheralsT7ee787.T7ee787bme280_sensor Tff7b72as T7ee787bme_sensor
Te6edf3bme_sensorTff7b72.Td2a8ffinitTb4b4b4(Te6edf3i2cTb4b4b4)

T8b949e# import peripherals.neopixel_led as neopixel_led
T8b949e# neopixel_led.init(pin=21)

T8b949e# import peripherals.gpio_control as gpio
T8b949e# gpio.init({"lamp": (2, "OUT")})

T8b949e# Battery: board-declared. init_battery() pulls the pin/divider from the board
T8b949e# preset (lora_boards.py) and self-disables if the board has no divider (e.g. the
T8b949e# XIAO ESP32-S3), so it's safe to list unconditionally — it reports nothing when
T8b949e# there's no battery wired.
Tff7b72import T7ee787peripheralsT7ee787.T7ee787adc_reader Tff7b72as T7ee787adc_reader
Te6edf3adc_readerTff7b72.Td2a8ffinit_batteryTb4b4b4(Te6edf3CONFIGTb4b4b4)

T8b949e# import peripherals.sds011_sensor as sds011_sensor
T8b949e# sds011_sensor.init(uart_id=1, tx_pin=43, rx_pin=44) # also add sds011_sensor to active_peripherals

T8b949e# List all active peripherals here (must match uncommented imports above)
Te6edf3active_peripherals Tff7b72= Tb4b4b4[Te6edf3bme_sensorTb4b4b4, Te6edf3adc_readerTb4b4b4]

Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)


Tff7b72def Td2a8ffconnect_wifiTb4b4b4(Te6edf3ssidTb4b4b4, Te6edf3passwordTb4b4b4, Te6edf3timeoutTff7b72=T79c0ff15Tb4b4b4)Tb4b4b4:
Tff7b72import T7ee787sys
Tff7b72import T7ee787network
Tff7b72import T7ee787time

Te6edf3platform Tff7b72= Te6edf3sysTff7b72.Td2a8ffplatform

Tff7b72if Te6edf3platform Tff7b72== Ta5d6ff"Ta5d6ffesp32Ta5d6ff"Tb4b4b4:
Te6edf3ap Tff7b72= Te6edf3networkTff7b72.Td2a8ffWLANTb4b4b4(Te6edf3networkTff7b72.Td2a8ffAP_IFTb4b4b4)
Tff7b72if Te6edf3apTff7b72.Td2a8ffactiveTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3apTff7b72.Td2a8ffactiveTb4b4b4(Tff7b72FalseTb4b4b4)

Te6edf3wlan Tff7b72= Te6edf3networkTff7b72.Td2a8ffWLANTb4b4b4(Te6edf3networkTff7b72.Td2a8ffSTA_IFTb4b4b4)
Te6edf3wlanTff7b72.Td2a8ffactiveTb4b4b4(Tff7b72TrueTb4b4b4)
Tff7b72if Tff7b72not Te6edf3wlanTff7b72.Td2a8ffisconnectedTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffConnecting to WiFi:Ta5d6ff"Tb4b4b4, Te6edf3ssidTb4b4b4)
Te6edf3wlanTff7b72.Td2a8ffconnectTb4b4b4(Te6edf3ssidTb4b4b4, Te6edf3passwordTb4b4b4)
Te6edf3start Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72while Tff7b72not Te6edf3wlanTff7b72.Td2a8ffisconnectedTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3start Tff7b72> Te6edf3timeoutTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffWiFi connection timed outTa5d6ff"Tb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.5Tb4b4b4)

Tff7b72if Te6edf3platform Tff7b72== Ta5d6ff"Ta5d6ffesp32Ta5d6ff"Tb4b4b4:
Te6edf3wlanTff7b72.Td2a8ffconfigTb4b4b4(Te6edf3pmTff7b72=T79c0ff0Tb4b4b4)
Tff7b72elif Te6edf3platform Tff7b72== Ta5d6ff"Ta5d6ffrp2Ta5d6ff"Tb4b4b4:
Te6edf3wlanTff7b72.Td2a8ffconfigTb4b4b4(Te6edf3pmTff7b72=T79c0ff0xa11140Tb4b4b4)

Te6edf3ip Tff7b72= Te6edf3wlanTff7b72.Td2a8ffifconfigTb4b4b4(Tb4b4b4)Tb4b4b4[T79c0ff0Tb4b4b4]
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffConnected! IP:Ta5d6ff"Tb4b4b4, Te6edf3ipTb4b4b4)

Tff7b72tryTb4b4b4:
Tff7b72import T7ee787ntptime
Te6edf3ntptimeTff7b72.Td2a8ffsettimeTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffNTP syncedTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffNTP sync failed:Ta5d6ff"Tb4b4b4, Te6edf3eTb4b4b4)

Tff7b72return Te6edf3ip


Tff7b72def Td2a8ffload_pagesTb4b4b4(Te6edf3destTb4b4b4, Te6edf3pages_dirTff7b72=Ta5d6ff"Ta5d6ffpagesTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e"""Load .mu pages from a directory and register them as request handlers.

Each .mu file becomes a NomadNet page at /page/<filename>.
Template variables {node_name}, {mem_free}, {uptime}, {sensor} are
substituted at serve time.
"""
Tff7b72import T7ee787os

Tff7b72tryTb4b4b4:
Te6edf3files Tff7b72= Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3pages_dirTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffPages directory not found:Ta5d6ff"Tb4b4b4, Te6edf3pages_dirTb4b4b4)
Tff7b72return T79c0ff0

Te6edf3count Tff7b72= T79c0ff0
Tff7b72for Te6edf3fname Tff7b72in Te6edf3filesTb4b4b4:
Tff7b72if Tff7b72not Te6edf3fnameTff7b72.Td2a8ffendswithTb4b4b4(Ta5d6ff"Ta5d6ff.muTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72continue

Te6edf3filepath Tff7b72= Te6edf3pages_dir Tff7b72+ Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72+ Te6edf3fname
Te6edf3page_path Tff7b72= Ta5d6ff"Ta5d6ff/page/Ta5d6ff" Tff7b72+ Te6edf3fname

Tff7b72def Td2a8fffmt_memTb4b4b4(Te6edf3bTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3b Tff7b72>Tff7b72= T79c0ff1048576Tb4b4b4:
Tff7b72return Ta5d6ff"Tffd700%.1fTa5d6ff MBTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3b Tff7b72/ T79c0ff1048576Tb4b4b4)
Tff7b72elif Te6edf3b Tff7b72>Tff7b72= T79c0ff1024Tb4b4b4:
Tff7b72return Ta5d6ff"Tffd700%.1fTa5d6ff KBTa5d6ff" Tff7b72% Tb4b4b4(Te6edf3b Tff7b72/ T79c0ff1024Tb4b4b4)
Tff7b72return Tffa657strTb4b4b4(Te6edf3bTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ff BTa5d6ff"

Tff7b72def Td2a8fffmt_uptimeTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4:
Te6edf3dTb4b4b4, Te6edf3s Tff7b72= Tffa657divmodTb4b4b4(Tffa657intTb4b4b4(Te6edf3sTb4b4b4)Tb4b4b4, T79c0ff86400Tb4b4b4)
Te6edf3hTb4b4b4, Te6edf3s Tff7b72= Tffa657divmodTb4b4b4(Te6edf3sTb4b4b4, T79c0ff3600Tb4b4b4)
Te6edf3mTb4b4b4, Te6edf3s Tff7b72= Tffa657divmodTb4b4b4(Te6edf3sTb4b4b4, T79c0ff60Tb4b4b4)
Te6edf3parts Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72if Te6edf3dTb4b4b4: Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Tffa657strTb4b4b4(Te6edf3dTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ffdTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3hTb4b4b4: Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Tffa657strTb4b4b4(Te6edf3hTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ffhTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3mTb4b4b4: Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Tffa657strTb4b4b4(Te6edf3mTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ffmTa5d6ff"Tb4b4b4)
Te6edf3partsTff7b72.Td2a8ffappendTb4b4b4(Tffa657strTb4b4b4(Te6edf3sTb4b4b4) Tff7b72+ Ta5d6ff"Ta5d6ffsTa5d6ff"Tb4b4b4)
Tff7b72return Ta5d6ff"Ta5d6ff Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3partsTb4b4b4)

Tff7b72def Td2a8ffmake_handlerTb4b4b4(Te6edf3fpathTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffhandlerTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3request_idTb4b4b4, Te6edf3link_idTb4b4b4, Te6edf3remote_identityTb4b4b4, Te6edf3requested_atTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3fpathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3page Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Ta5d6ffbTa5d6ff"Ta5d6ff>Page Not FoundTffea00\nTa5d6ff"
Te6edf3page Tff7b72= Te6edf3pageTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff"Tffd700{node_name}Ta5d6ff"Tb4b4b4, Te6edf3NODE_NAMETff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3page Tff7b72= Te6edf3pageTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff"Tffd700{mem_free}Ta5d6ff"Tb4b4b4, Te6edf3fmt_memTb4b4b4(Te6edf3gcTff7b72.Td2a8ffmem_freeTb4b4b4(Tb4b4b4)Tb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72exceptTb4b4b4:
Te6edf3page Tff7b72= Te6edf3pageTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff"Tffd700{mem_free}Ta5d6ff"Tb4b4b4, Ta5d6ffbTa5d6ff"Ta5d6ff?Ta5d6ff"Tb4b4b4)
Te6edf3page Tff7b72= Te6edf3pageTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff"Tffd700{uptime}Ta5d6ff"Tb4b4b4, Te6edf3fmt_uptimeTb4b4b4(Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3_boot_timeTb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
T8b949e# Sensor data from all active peripherals
Te6edf3results Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3p Tff7b72in Te6edf3active_peripheralsTb4b4b4:
Te6edf3result Tff7b72= Te6edf3pTff7b72.Td2a8ffprocessTb4b4b4(Ta5d6ff"Ta5d6ffsensorTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3resultTb4b4b4:
Te6edf3resultsTff7b72.Td2a8ffappendTb4b4b4(Te6edf3resultTb4b4b4)
Te6edf3sensor_text Tff7b72= Ta5d6ff"Tffea00\nTa5d6ff Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3resultsTb4b4b4) Tff7b72if Te6edf3results Tff7b72else Ta5d6ff"Ta5d6ffno sensorTa5d6ff"
Te6edf3page Tff7b72= Te6edf3pageTff7b72.Td2a8ffreplaceTb4b4b4(Ta5d6ffbTa5d6ff"Tffd700{sensor}Ta5d6ff"Tb4b4b4, Te6edf3sensor_textTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3page
Tff7b72return Te6edf3handler

Te6edf3destTff7b72.Td2a8ffregister_request_handlerTb4b4b4(
Te6edf3page_pathTb4b4b4,
Te6edf3response_generatorTff7b72=Te6edf3make_handlerTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4,
Te6edf3allowTff7b72=Te6edf3destTff7b72.Td2a8ffALLOW_ALLTb4b4b4,
Tb4b4b4)
Te6edf3count Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffLoaded page:Ta5d6ff"Tb4b4b4, Te6edf3page_pathTb4b4b4, Ta5d6ff"Ta5d6fffromTa5d6ff"Tb4b4b4, Te6edf3filepathTb4b4b4)

Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffLoadedTa5d6ff"Tb4b4b4, Te6edf3countTb4b4b4, Ta5d6ff"Ta5d6ffpage(s) fromTa5d6ff"Tb4b4b4, Te6edf3pages_dir Tff7b72+ Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3count


Tff7b72def Td2a8ffload_filesTb4b4b4(Te6edf3destTb4b4b4, Te6edf3files_dirTff7b72=Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4)Tb4b4b4:
T8b949e"""Load files from a directory and register them as download handlers.

Each file becomes downloadable at /file/<filename> via NomadNet link syntax:
[Download text`:/file/<filename>]
Large files (>417B) are automatically served via Resource transfer.
"""
Tff7b72import T7ee787os

Tff7b72tryTb4b4b4:
Te6edf3flist Tff7b72= Te6edf3osTff7b72.Td2a8fflistdirTb4b4b4(Te6edf3files_dirTb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFiles directory not found:Ta5d6ff"Tb4b4b4, Te6edf3files_dirTb4b4b4)
Tff7b72return T79c0ff0

Te6edf3count Tff7b72= T79c0ff0
Tff7b72for Te6edf3fname Tff7b72in Te6edf3flistTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3files_dir Tff7b72+ Ta5d6ff"Ta5d6ff/Ta5d6ff" Tff7b72+ Te6edf3fname
Te6edf3file_path Tff7b72= Ta5d6ff"Ta5d6ff/file/Ta5d6ff" Tff7b72+ Te6edf3fname

Tff7b72def Td2a8ffmake_handlerTb4b4b4(Te6edf3fpathTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffhandlerTb4b4b4(Te6edf3pathTb4b4b4, Te6edf3dataTb4b4b4, Te6edf3request_idTb4b4b4, Te6edf3link_idTb4b4b4, Te6edf3remote_identityTb4b4b4, Te6edf3requested_atTb4b4b4)Tb4b4b4:
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Te6edf3fpathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3file_data Tff7b72= Te6edf3fTff7b72.Td2a8ffreadTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149OSErrorTb4b4b4:
Tff7b72return Tff7b72None
Tff7b72return Tb4b4b4[Te6edf3nameTb4b4b4, Te6edf3file_dataTb4b4b4]
Tff7b72return Te6edf3handler

Te6edf3destTff7b72.Td2a8ffregister_request_handlerTb4b4b4(
Te6edf3file_pathTb4b4b4,
Te6edf3response_generatorTff7b72=Te6edf3make_handlerTb4b4b4(Te6edf3filepathTb4b4b4, Te6edf3fnameTb4b4b4)Tb4b4b4,
Te6edf3allowTff7b72=Te6edf3destTff7b72.Td2a8ffALLOW_ALLTb4b4b4,
Tb4b4b4)
Te6edf3count Tff7b72+Tff7b72= T79c0ff1
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffRegistered file:Ta5d6ff"Tb4b4b4, Te6edf3file_pathTb4b4b4)

Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffRegisteredTa5d6ff"Tb4b4b4, Te6edf3countTb4b4b4, Ta5d6ff"Ta5d6fffile(s) fromTa5d6ff"Tb4b4b4, Te6edf3files_dir Tff7b72+ Ta5d6ff"Ta5d6ff/Ta5d6ff"Tb4b4b4)
Tff7b72return Te6edf3count


Tff7b72def Td2a8ffneeds_wifiTb4b4b4(Te6edf3configTb4b4b4)Tb4b4b4:
T8b949e"""Check if any UDP or TCP interface is enabled in config."""
Tff7b72for Te6edf3iface Tff7b72in Te6edf3configTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinterfacesTa5d6ff"Tb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3ifaceTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffenabledTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4) Tff7b72and Te6edf3ifaceTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff"Tb4b4b4) Tff7b72in Tb4b4b4(
Ta5d6ff"Ta5d6ffUDPInterfaceTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTCPClientInterfaceTa5d6ff"Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72return Tff7b72True
Tff7b72return Tff7b72False


Tff7b72def Td2a8ffmainTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72import T7ee787uasyncio Tff7b72as T7ee787asyncio

Tff7b72if Te6edf3needs_wifiTb4b4b4(Te6edf3CONFIGTb4b4b4)Tb4b4b4:
Te6edf3connect_wifiTb4b4b4(Te6edf3WIFI_SSIDTb4b4b4, Te6edf3WIFI_PASSTb4b4b4)
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

Tff7b72from T7ee787urns Tff7b72import Te6edf3ReticulumTb4b4b4, Te6edf3Destination
Tff7b72from T7ee787urnsT7ee787.T7ee787log Tff7b72import Te6edf3LOG_NONETb4b4b4, Te6edf3LOG_NOTICETb4b4b4, Te6edf3LOG_DEBUG

Te6edf3log_map Tff7b72= Tb4b4b4{T79c0ff0Tb4b4b4: Te6edf3LOG_NONETb4b4b4, T79c0ff1Tb4b4b4: Te6edf3LOG_NOTICETb4b4b4, T79c0ff2Tb4b4b4: Te6edf3LOG_DEBUGTb4b4b4}
Te6edf3rns Tff7b72= Te6edf3ReticulumTb4b4b4(Te6edf3loglevelTff7b72=Te6edf3log_mapTff7b72.Td2a8ffgetTb4b4b4(Te6edf3DEBUGTb4b4b4, Te6edf3LOG_NOTICETb4b4b4)Tb4b4b4)
Te6edf3rnsTff7b72.Td2a8ffconfig Tff7b72= Te6edf3CONFIG
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

T8b949e# Create NomadNet node destination: nomadnetwork.node
Te6edf3dest Tff7b72= Te6edf3DestinationTb4b4b4(
Te6edf3rnsTff7b72.Td2a8ffidentityTb4b4b4, Te6edf3DestinationTff7b72.Td2a8ffINTb4b4b4, Te6edf3DestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Ta5d6ff"Ta5d6ffnomadnetworkTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffnodeTa5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3destTff7b72.Td2a8ffset_default_app_dataTb4b4b4(Te6edf3NODE_NAMETff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3destTff7b72.Td2a8ffaccepts_linksTb4b4b4(Tff7b72TrueTb4b4b4)

T8b949e# Load pages and downloadable files
Te6edf3load_pagesTb4b4b4(Te6edf3destTb4b4b4)
Te6edf3load_filesTb4b4b4(Te6edf3destTb4b4b4)

Tff7b72def Td2a8ffon_linkTb4b4b4(Te6edf3linkTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff[Link] Established:Ta5d6ff"Tb4b4b4, Te6edf3linkTb4b4b4)

Te6edf3destTff7b72.Td2a8ffset_link_established_callbackTb4b4b4(Te6edf3on_linkTb4b4b4)
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

Te6edf3rnsTff7b72.Td2a8ffsetup_interfacesTb4b4b4(Tb4b4b4)
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffNomadNet node address:Ta5d6ff"Tb4b4b4, Te6edf3destTff7b72.Td2a8ffhexhashTb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffFree memory:Ta5d6ff"Tb4b4b4, Te6edf3gcTff7b72.Td2a8ffmem_freeTb4b4b4(Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffbytesTa5d6ff"Tb4b4b4)
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffRunning... (Ctrl+C to stop)Ta5d6ff"Tb4b4b4)

Tff7b72async Tff7b72def Td2a8ffinitial_announceTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff3Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3destTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffAnnounced as:Ta5d6ff"Tb4b4b4, Te6edf3NODE_NAMETb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffAnnounce error:Ta5d6ff"Tb4b4b4, Te6edf3eTb4b4b4)
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

Tff7b72async Tff7b72def Td2a8ffreannounce_loopTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72while Tff7b72TrueTb4b4b4:
Tff7b72await Te6edf3asyncioTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff300Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3destTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ff[Re-announced]Ta5d6ff"Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3eTb4b4b4:
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff2Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffRe-announce error:Ta5d6ff"Tb4b4b4, Te6edf3eTb4b4b4)
Te6edf3gcTff7b72.Td2a8ffcollectTb4b4b4(Tb4b4b4)

Te6edf3_original_run Tff7b72= Te6edf3rnsTff7b72.Td2a8ffrun

Tff7b72async Tff7b72def Td2a8ffrun_with_announceTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3asyncioTff7b72.Td2a8ffcreate_taskTb4b4b4(Te6edf3initial_announceTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3asyncioTff7b72.Td2a8ffcreate_taskTb4b4b4(Te6edf3reannounce_loopTb4b4b4(Tb4b4b4)Tb4b4b4)
T8b949e# Start SDS011 periodic measurement if active
T8b949e# if sds011_sensor.sensor: sds011_sensor.start()
Tff7b72await Te6edf3_original_runTb4b4b4(Tb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3asyncioTff7b72.Td2a8ffrunTb4b4b4(Te6edf3run_with_announceTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72except Tf85149KeyboardInterruptTb4b4b4:
Te6edf3rnsTff7b72.Td2a8ffshutdownTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3DEBUG Tff7b72>Tff7b72= T79c0ff1Tb4b4b4:
Tffa657printTb4b4b4(Ta5d6ff"Ta5d6ffShutdown completeTa5d6ff"Tb4b4b4)


Te6edf3mainTb4b4b4(Tb4b4b4)

Served by rngit 1.5.2 - Generated in 0.06s